<?php

namespace App\Services;

use AdaPay\AdaPay;
use App\Constant;
use App\Enums\DivideStatus;
use App\Models\AgentConfig;
use App\Models\Order;
use App\Models\OrderPayment;
use App\Models\Store;
use App\Models\YeepayBank;
use CURLFile;
use DateTime;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;

class AdaPayService extends AdaPay
{
    public $endpoint;
    private $notifyUrl;
    private $appId;

    private $config;

    public function __construct($config)
    {
        $this->notifyUrl = config('services.adapay.notify_url');
        $this->config = $config;

        //define('DEBUG', true);
        define('SDK_VERSION', 'v1.4.4');
        define('GATE_WAY_URL', 'https://%s.adapay.tech');
        define('LOG', base_path() . '/storage/logs/adapay/');

        $this->appId = $config[AgentConfig::ADAPAY_APP_ID];

        AdaPay::init(
            [
                'api_key_live' => $config[AgentConfig::ADAPAY_API_KEY],
                'rsa_public_key' => $config[AgentConfig::ADAPAY_RSA_PUBLIC_KEY],
                'rsa_private_key' => $config[AgentConfig::ADAPAY_RSA_PRIVATE_KEY],
            ]
        );

        parent::__construct();
    }

    /**
     * 创建企业用户对象
     *
     * @param mixed $data
     *
     * @return array|void
     */
    public function corpMemberCreat($data)
    {
        $this->endpoint = '/v1/corp_members';

        $provCode = Str::limit($data['province'], 2, '');
        if (in_array($provCode, ['11', '12', '31', '50'])) {
            $areaCode = $provCode . '00';
        } else {
            $areaCode = Str::limit($data['city'], 4, '');
        }
        $provCode = '00' . $provCode;

        $bank = YeepayBank::query()->where('code', $data['bankCode'])->first();
        if (!$bank || empty($bank->adapay_code)) {
            throw new \Exception('不支持该银行开户');
        }

        $memberParams = [
            'app_id' => $this->appId,
            'member_id' => 'BBT' . date('YmdHis') . rand(1000, 9999),
            'order_no' => date('YmdHis') . rand(100000, 999999),
            'name' => $data['name'],
            'prov_code' => $provCode,
            'area_code' => $areaCode,
            'social_credit_code' => $data['licenceNo'],
            'social_credit_code_expires' => Carbon::parse($data['licenceNoExpires'])->format('Ymd'),
            'business_scope' => $data['business_scope'],
            'legal_person' => $data['legalName'],
            'legal_cert_id' => $data['legalLicenceNo'],
            'legal_cert_id_expires' => Carbon::parse($data['legalLicenceNoExpires'])->format('Ymd'),
            'legal_mp' => $data['contactMobile'],
            'address' => $data['address'],
            'zip_code' => '',
            'telphone' => '',
            'email' => '',
            'attach_file' => new CURLFile($data['attach_url']),
            'bank_code' => $bank->adapay_code,
            'bank_acct_type' => '1', //1-对公；2-对私，如果需要自动开结算账户，本字段必填
            'card_no' => $data['bankCardNo'],
            'card_name' => $data['name'], //如果需要自动开结算账户，本字段必填
            'notify_url' => $this->notifyUrl,
        ];

        $requestParams = $this->do_empty_data($memberParams);
        $reqUrl = $this->gateWayUrl . $this->endpoint;
        ksort($requestParams);
        $sign_request_params = $requestParams;
        unset($sign_request_params['attach_file']);
        ksort($sign_request_params);
        $sign_str = $this->ada_tools->createLinkstring($sign_request_params);

        $header = $this->get_request_header($reqUrl, $sign_str, self::$headerEmpty);
        $this->result = $this->ada_request->curl_request($reqUrl, $requestParams, $header);

        \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->info('CORP_MEMBER_CREAT', $memberParams);
        if ($this->isError()) {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->error('CORP_MEMBER_CREAT_FAIL', $this->result ?: []);

            throw new \Exception($this->result['error_msg']);
        }
        \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->info('CORP_MEMBER_CREAT_RESP', $this->result);

        return [
            'applicationStatus' => 'REVIEWING',
            'merchantNo' => $memberParams['member_id'],
        ];
    }

    /**
     * 查询企业用户对象
     *
     * @return array|void
     */
    public function corpMemberQuery()
    {
        $this->endpoint = '/v1/corp_members';

        $params = [
            'app_id' => $this->appId,
            'member_id' => 'vrleo_business_test_202210261533255172',
        ];
        ksort($params);
        $request_params = $this->do_empty_data($params);
        $reqUrl = $this->gateWayUrl . $this->endpoint . '/' . $params['member_id'];
        $header = $this->get_request_header($reqUrl, http_build_query($request_params), self::$headerText);
        $this->result = $this->ada_request->curl_request(
            $reqUrl . '?' . http_build_query($request_params),
            '',
            $header,
            false
        );

        if ($this->isError()) {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->error('CORP_MEMBER_QUERY', $this->result);
        } else {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->info('CORP_MEMBER_QUERY', $this->result);

            return $this->result;
        }
    }

    /**
     * 创建结算账户（用不到）.
     *
     * @param $memberId
     * @param mixed $accountInfo
     *
     * @return array|void
     */
    public function settlePublicAccount($memberId, $accountInfo)
    {
        $this->endpoint = '/v1/settle_accounts';

        $params = [
            'app_id' => $this->appId,
            'member_id' => $memberId,
            'channel' => 'bank_account',
            'account_info' => [
                'card_id' => Arr::get($accountInfo, 'card_id'),
                'card_name' => Arr::get($accountInfo, 'card_name'),
                'bank_code' => Arr::get($accountInfo, 'bank_code'),
                'bank_name' => Arr::get($accountInfo, 'bank_name'),
                'tel_no' => Arr::get($accountInfo, 'tel_no'),
                'bank_acct_type' => 1, //对公
                'prov_code' => Arr::get($accountInfo, 'prov_code'),
                'area_code' => Arr::get($accountInfo, 'area_code'),
            ],
        ];

        $requestParams = $params;
        $requestParams = $this->do_empty_data($requestParams);
        $reqUrl = $this->gateWayUrl . $this->endpoint;
        $header = $this->get_request_header($reqUrl, $requestParams, self::$header);
        $this->result = $this->ada_request->curl_request($reqUrl, $requestParams, $header, $is_json = true);

        if ($this->isError()) {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->error('SETTLE_ACCOUNT', $this->result);
        } else {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->info('SETTLE_ACCOUNT', $this->result);

            return $this->result;
        }
    }

    /**
     * 获取收银台支付链接.
     *
     * @param $orderNo
     * @param $amount
     * @param $goodsName
     * @param $userNo
     * @param $walletUserNo
     * @param $redirectUrl
     * @param mixed $extra
     *
     * @return mixed|void
     */
    public function getUnionPayLink(
        $orderNo,
        $amount,
        $goodsName,
        $userNo,
        $walletUserNo,
        $redirectUrl,
        DateTime $expireTime,
        $extra = []
    ) {
        $this->getGateWayUrl('page');
        $this->endpoint = '/v1/checkout';

        // 处理分账数据

        /** @var OrderPayment $payment */
        $payment = OrderPayment::query()->where('out_order_no', $orderNo)->first();

        /** @var Order $order */
        $order = Order::query()->find($payment->order_id);
        if ($payment && $order) {
            $merchantFee = 0;
            $orderAmount = $payment->pay_amount - $merchantFee;
            $receiveAmount = $orderAmount;
            $storeFee = $userFee = 0;
            $agentConfigs = $this->config;
            // 平台交易手续费
            if ($order->is_resale) {
                $serviceFeeRate = Arr::get($agentConfigs, AgentConfig::PAY_RESALE_SERVICE_FEE_RATE, 0);
            } else {
                $serviceFeeRate = Arr::get($agentConfigs, AgentConfig::PAY_SERVICE_FEE_RATE, 0);
            }
            if ('' == $serviceFeeRate) {
                $serviceFeeRate = 0;
            }
            $serviceFee = floor($orderAmount * $serviceFeeRate / 100) - $merchantFee;
            $serviceFee = min($serviceFee, $receiveAmount);

            // 门店交易手续费
            if ($order->product->store_id) {
                /** @var Store $store */
                $store = Store::query()->find($order->product->store_id);
                if ($store && $store->divide_account) {
                    $agentFee = floor($orderAmount * $store->agent_service_fee_rate / 100);
                    $storeFee = $receiveAmount - $serviceFee - $storeFee - $agentFee;
                } else {
                    $agentFee = $receiveAmount - $serviceFee - $storeFee;
                }
            } else {
                $agentFee = $receiveAmount - $serviceFee - $storeFee;
            }

            $payment->receive_amount = ($orderAmount - $merchantFee);
            $payment->platform_receive_amount = $serviceFee;
            $payment->agent_receive_amount = $agentFee;
            $payment->user_receive_amount = $userFee;
            $payment->store_receive_amount = $storeFee;
            $payment->divide_status = DivideStatus::DIVIDING;
            $payment->save();
        }

        $divMembers = [];
        if (!empty($serviceFee) && !empty($this->config[AgentConfig::ADAPAY_DIVIDE_ID])) {
            $divMembers[] = [
                'member_id' => $this->config[AgentConfig::ADAPAY_DIVIDE_ID],
                'amount' => formatPrice($serviceFee / 100),
                'fee_flag' => 'N',
            ];

            if (!empty($agentFee)) {
                $divMembers[] = ['member_id' => 0, 'amount' => formatPrice($agentFee / 100), 'fee_flag' => 'Y'];
            }
            if (!empty($store) && !empty($storeFee)) {
                $divMembers[] = [
                    'member_id' => $store->divide_account,
                    'amount' => formatPrice($storeFee / 100),
                    'fee_flag' => 'N',
                ];
            }
        }

        $checkoutParams = [
            'app_id' => $this->appId,
            'member_id' => $userNo,
            'order_no' => $orderNo,
            'pay_amt' => formatPrice($amount),
            'goods_title' => $goodsName,
            'goods_desc' => $goodsName,
            'div_members' => $divMembers,
            'time_expire' => $expireTime->format('YmdHis'),
            'description' => '',
            'notify_url' => $this->notifyUrl,
            'callback_url' => $redirectUrl,
        ];

        \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->error('CHECKOUT', $checkoutParams);

        $request_params = $this->do_empty_data($checkoutParams);
        $reqUrl = $this->gateWayUrl . $this->endpoint;
        $header = $this->get_request_header($reqUrl, $request_params, self::$header);
        $this->result = $this->ada_request->curl_request($reqUrl, $request_params, $header, $is_json = true);

        if ($this->isError()) {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->error('CHECKOUT', $this->result);

            throw new \Exception($this->result['error_msg']);
        }
        \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->info('CHECKOUT', $this->result);

        return $this->result['expend']['pay_url'];
    }

    /**
     * 支付退款.
     *
     * @param $paymentId
     * @param $refundOrderNo
     * @param $amount
     *
     * @return array|void
     */
    public function refund($paymentId, $refundOrderNo, $amount)
    {
        $this->endpoint = '/v1/payments';

        $params = [
            'payment_id' => $paymentId, // 原交易支付对象ID
            'refund_order_no' => $refundOrderNo, // 退款订单号
            'refund_amt' => $amount, // 退款金额
            'reason' => sprintf('%s支付退款', $refundOrderNo),
            'expend' => '',
            'device_info' => '',
        ];

        $request_params = $params;
        $charge_id = isset($params['payment_id']) ? $params['payment_id'] : '';
        $request_params = $this->do_empty_data($request_params);
        $req_url = $this->gateWayUrl . $this->endpoint . '/' . $charge_id . '/refunds';
        $header = $this->get_request_header($req_url, $request_params, self::$header);
        $this->result = $this->ada_request->curl_request($req_url, $request_params, $header, $is_json = true);

        if ($this->isError()) {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->error('REFUND', $this->result);
        } else {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->info('REFUND', $this->result);

            return $this->result;
        }
    }

    /**
     * 查询支付状态
     *
     * @param $orderNo
     *
     * @return array|void
     */
    public function queryOrder($orderNo)
    {
        $this->getGateWayUrl('page');
        $this->endpoint = '/v1/checkout';
        $params = ['app_id' => $this->appId, 'order_no' => $orderNo];

        ksort($params);
        $request_params = $this->do_empty_data($params);
        $req_url = $this->gateWayUrl . $this->endpoint . '/list';
        $header = $this->get_request_header($req_url, http_build_query($request_params), self::$headerText);
        $this->result = $this->ada_request->curl_request(
            $req_url . '?' . http_build_query($request_params),
            '',
            $header,
            false
        );

        if ($this->isError()) {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->error('QUERY', $this->result);
        } else {
            \Log::channel(Constant::LOG_CHANNEL_ADAPAY)->info('QUERY', $this->result);
            if (!empty($this->result['checkouts'])) {
                $order = $this->result['checkouts'][0];
                if ('failed' == $order['status']) {
                    return ['order_no' => $order['order_no'], 'status' => 'failed'];
                }
                if ('pending' == $order['status']) {
                    return ['order_no' => $order['order_no'], 'status' => 'PROCESSING'];
                }
                if ('succeeded' == $order['status']) {
                    return ['order_no' => $order['order_no'], 'status' => 'SUCCESS'];
                }
            }

            return $this->result;
        }
    }

    /**
     * 关闭订单.
     *
     * @param $orderId
     * @param $uniqueOrderNo
     */
    public function closeOrder($orderId, $uniqueOrderNo): string
    {
        return '';
    }

    /**
     * 异步消息签名验证
     *
     * @param $sign
     * @param $paramsStr
     */
    public function verifySign($sign, $paramsStr): bool
    {
        //return $this->ada_tools->verifySign($sign, $paramsStr);
        return true;
    }
}
